// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_OHOS_H_
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_OHOS_H_

#include <list>
#include "content/browser/accessibility/browser_accessibility.h"

namespace content {
class BrowserAccessibilityManager;

// A `BrowserAccessibility` object represents one node in the accessibility tree
// on the browser side. It wraps an `AXNode` and assists in exposing
// web-specific information from the node. It's owned by a
// `BrowserAccessibilityManager`.
//
// There are subclasses of BrowserAccessibility for each platform where we
// implement some of the native accessibility APIs that are only specific to the
// Web.
class CONTENT_EXPORT BrowserAccessibilityOHOS : public BrowserAccessibility {
 public:
  BrowserAccessibilityOHOS(const BrowserAccessibilityOHOS&) = delete;

  BrowserAccessibilityOHOS& operator=(const BrowserAccessibilityOHOS&) = delete;

  ~BrowserAccessibilityOHOS() override;

  int32_t GetAccessibilityId() const;

  bool IsEnabled() const;

  bool IsFocusable() const;

  std::string GetHint() const;

  bool IsHint() const;

  bool IsChecked() const;

  bool IsSelected() const;

  bool IsScrollable() const;

  bool IsCheckable() const;

  bool IsMultiLine() const;

  bool CanOpenPopup() const;

  bool IsContentInvalid() const;

  std::string GetContentInvalidErrorMessage() const;

  int32_t OHOSInputType() const;

  int32_t OHOSLiveRegionType() const;

  int32_t GetSelectionStart() const;

  int32_t GetSelectionEnd() const;

  size_t GetItemCount() const;

  int32_t RowCount() const;

  int32_t ColumnCount() const;

  int32_t RowIndex() const;

  int32_t RowSpan() const;

  int32_t ColumnIndex() const;

  int32_t ColumnSpan() const;

  bool IsHierarchical() const;

  bool IsCollection() const;

  bool IsCollectionItem() const;

  bool IsHeading() const;

  static BrowserAccessibilityOHOS* GetFromAccessibilityId(
      int32_t accessibility_id);

  const char* GetClassName() const;

  const BrowserAccessibilityOHOS* GetAccessibilityNodeByFocusMove(
      int32_t direction) const;

 protected:
  BrowserAccessibilityOHOS(BrowserAccessibilityManager* manager,
                           ui::AXNode* node);

  friend class BrowserAccessibility;

 private:
  bool ShouldExposeValueAsName() const;

  bool IsRangeControlWithoutAriaValueText() const;

  bool HasOnlyTextChildren() const;

  const char* AXRoleToOHOSClassName(ax::mojom::Role role,
                                    bool has_parent) const;

  void AddFocusableNode(
      std::list<const BrowserAccessibilityOHOS*>& nodeList) const;

  const BrowserAccessibilityOHOS* FindNodeInRelativeDirection(
      const std::list<const BrowserAccessibilityOHOS*>& nodeList,
      int32_t direction) const;

  const BrowserAccessibilityOHOS* FindNodeInAbsoluteDirection(
      const std::list<const BrowserAccessibilityOHOS*>& nodeList,
      int32_t direction) const;

  const BrowserAccessibilityOHOS* GetNextFocusableNode(
      const std::list<const BrowserAccessibilityOHOS*>& nodeList) const;

  const BrowserAccessibilityOHOS* GetPreviousFocusableNode(
      const std::list<const BrowserAccessibilityOHOS*>& nodeList) const;

  static bool CheckRectBeam(const gfx::Rect& nodeRect,
                            const gfx::Rect& itemRect,
                            const int32_t direction);

  static bool IsToDirectionOf(const gfx::Rect& nodeRect,
                              const gfx::Rect& itemRect,
                              const int32_t direction);

  static double MajorAxisDistanceToFarEdge(const gfx::Rect& nodeRect,
                                           const gfx::Rect& itemRect,
                                           const int32_t direction);

  static double MajorAxisDistance(const gfx::Rect& nodeRect,
                                  const gfx::Rect& itemRect,
                                  const int32_t direction);

  static double MinorAxisDistance(const gfx::Rect& nodeRect,
                                  const gfx::Rect& itemRect,
                                  const int32_t direction);

  static double GetWeightedDistanceFor(double majorAxisDistance,
                                       double minorAxisDistance);

  static bool IsCandidateRect(const gfx::Rect& nodeRect,
                              const gfx::Rect& itemRect,
                              const int32_t direction);

  // Check whether rect1 is outright better than rect2.
  static bool OutrightBetter(const gfx::Rect& nodeRect,
                             const int32_t direction,
                             const gfx::Rect& Rect1,
                             const gfx::Rect& Rect2);

  static bool CheckBetterRect(const gfx::Rect& nodeRect,
                              const int32_t direction,
                              const gfx::Rect& itemRect,
                              const gfx::Rect& tempBest);

  int32_t accessibility_id_ = -1;
};
}  // namespace content

#endif  // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_OHOS_H_